package concurrent.read;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;

/**
 * Created by zzf on 2017/4/29.
 */
public class ReadThreadPool extends ThreadPoolExecutor {
    private final ThreadLocal<Long> startTime = new ThreadLocal<>();
    private final AtomicLong numTask = new AtomicLong();
    private final AtomicLong totalTime = new AtomicLong();

    public static ReadThreadPool newReadThreadPool(int nThreads) {
      return new ReadThreadPool(nThreads);
    }

    public static ReadThreadPool newReadThreadPool(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) {
        return new ReadThreadPool(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
    }

    private ReadThreadPool(int nThreads) {
        super(nThreads, nThreads,
                0L, TimeUnit.MILLISECONDS,
                new LinkedBlockingQueue<Runnable>());
    }

    private ReadThreadPool(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) {
        super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
    }

    protected void beforeExecute(Thread thread, Runnable runnable) {
        System.out.println(String.format("Thread %s:start reading %s",thread,runnable));
        startTime.set(System.nanoTime());
    }

    protected void afterExecute(Runnable runnable, Throwable throwable) {

      try{
          long endTime = System.nanoTime();
          long taskTime = endTime - startTime.get();
          numTask.incrementAndGet();
          totalTime.addAndGet(taskTime);

          System.out.println(String.format("Thread %s: end reading %s,time =%dns",taskTime,runnable,taskTime));
      }finally {
          super.afterExecute(runnable, throwable);
      }


    }
}
